﻿using CIS.DB;
using CIS.Web.Common;
using CIS.Web.Models;
using CIS.Web.Properties;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace CIS.Web.Controllers
{
	[RoutePrefix("ConferenceScheduleEvent")]
	public class ConferenceScheduleEventController : BaseDbController
	{
		private string _importMessage;

		[Route("Index/{ConferenceId}")]
		public async Task<ActionResult> Index(string conferenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", conferenceId);

			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.Status == ConstValues.Status.正常 &&
						x.ID == conferenceId);

			ViewBag.ConferenceId = conferenceId;
			ViewBag.ConferenceName = conferenceMaster.ConferenceName;
			ViewBag.ControllerName = Resources.ScheduleEventMaster;
			ViewBag.Language = conferenceMaster.IsInternational ? ConstValues.Language.En : ConstValues.Language.Cn;

			var model = new ConferenceScheduleEventModel();
			model.ConferenceId = conferenceId;
			LoginUser.ConferenceFunctionIdList = Utility.GetConferenceFunctionIdList(conferenceId);
			return View(model);
		}

		public async Task<JsonCamelCaseResult> GetData(int? page, int? rows, string sort, string order, ConferenceScheduleEventModel model)
		{
			int take = rows ?? ConstValues.DefaultGridRows;
			int skip = ((page ?? 1) - 1) * take;

			var sql = DbContext.ScheduleEventMaster.AsNoTracking()
					.Where(x => !string.IsNullOrEmpty(x.Status) &&
						x.ConferenceId == model.ConferenceId)
					.GroupJoin(DbContext.TopicMaster.AsNoTracking()
						.Where(x => x.ConferenceId == model.ConferenceId),
						scheduleEvent => scheduleEvent.TopicId,
						topicMaster => topicMaster.ID,
						(scheduleEvent, topicMaster) => new
						{
							ID = scheduleEvent.ID,
							ConferenceId = scheduleEvent.ConferenceId,
							EventName = scheduleEvent.EventName,
							Duration = scheduleEvent.Duration,
							TopicId = scheduleEvent.TopicId,
							TopicName = topicMaster.FirstOrDefault().TopicName,
							Status = scheduleEvent.Status,
							ScheduleStatus = scheduleEvent.ScheduleStatus,
							Sort = scheduleEvent.Sort,
							Remark = scheduleEvent.Remark,
							Creator = scheduleEvent.Creator,
							CreateIP = scheduleEvent.CreateIP,
							CreateDate = scheduleEvent.CreateDate,
							UpdateDate = scheduleEvent.UpdateDate
						});

			if (!string.IsNullOrWhiteSpace(model.SelEventName))
			{
				sql = sql.Where(x => x.EventName.Contains(model.SelEventName));
			}

			int total = await sql.CountAsync();

			if (!string.IsNullOrEmpty(sort))
			{
				sql = sql.OrderBy(sort + ConstValues.chrSpace + order).Skip(skip).Take(take);
			}
			else
			{
				sql = sql.OrderBy(x => x.Sort).ThenByDescending(x => x.UpdateDate).ThenBy(x => x.EventName).Skip(skip).Take(take);
			}

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				ID = x.ID,
				ConferenceId = x.ConferenceId,
				EventName = x.EventName,
				Duration = x.Duration,
				TopicName = x.TopicName,
				Status = x.Status,
				ScheduleStatus = x.ScheduleStatus,
				Sort = x.Sort,
				Remark = x.Remark,
				Creator = x.Creator,
				CreateIP = x.CreateIP,
				CreateDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.CreateDate.Value.ToString("yyyy-MM-dd") :
							x.CreateDate.Value.ToString("MM/dd/yyyy")
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetEditData(string id)
		{
			var result = await DbContext.ScheduleEventMaster.AsNoTracking().FirstOrDefaultAsync(x => x.ID == id);

			if (result != null)
			{
				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Create/{ConferenceId}")]
		public async Task<JsonResult> Create(ConferenceScheduleEventModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var count = model.Count.HasValue ? model.Count.Value : 1;
			using (var transaction = DbContext.Database.BeginTransaction())
			{
				for (var i = 0; i < count; i++)
				{
					var scheduleMaster = new ScheduleEventMaster
					{
						ID = Utility.GetTableId(ConstValues.TableName.ScheduleEventMaster),
						ConferenceId = model.ConferenceId,
						EventName = model.EventName,
						Duration = model.Duration,
						TopicId = model.TopicId,
						Chairman = string.Empty,
						ChairmanMail = string.Empty,
						ScheduleStatus = ConstValues.ScheduleStatus.待安排,
						Status = model.Status,
						Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort,
						Remark = model.Remark?.Trim(),
						Creator = LoginUser.UserName,
						CreateIP = LoginUser.IP,
						CreateDate = DateTime.Now
					};
					DbContext.ScheduleEventMaster.Add(scheduleMaster);
					await DbContext.SaveChangesAsync();
				}
				
				transaction.Commit();
			}
			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Modify/{ConferenceId}")]
		public async Task<JsonResult> Modify(ConferenceScheduleEventModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var exist = await DbContext.ScheduleInfo.AsNoTracking()
					.Where(x => x.ContributeId == model.Id).ToListAsync();

			if (exist.Count > 0)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotChange),
						JsonRequestBehavior.AllowGet);
			}

			var result = await DbContext.ScheduleEventMaster
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result != null)
			{
				if (result.ScheduleStatus == ConstValues.ScheduleStatus.已安排)
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotChange),
							JsonRequestBehavior.AllowGet);
				}

				result.EventName = model.EventName?.Trim();
				result.Duration = model.Duration;
				result.TopicId = model.TopicId;
				result.ScheduleStatus = ConstValues.ScheduleStatus.待安排;
				result.Status = model.Status;
				result.Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort;
				result.Remark = model.Remark?.Trim();
				result.Updater = LoginUser.UserName;
				result.UpdateIP = LoginUser.IP;
				result.UpdateDate = DateTime.Now;

				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Delete/{ConferenceId}")]
		public async Task<JsonResult> Delete(ConferenceScheduleEventModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var exist = await DbContext.ScheduleInfo.AsNoTracking()
					.Where(x => x.ContributeId == model.Id).ToListAsync();

			if (exist.Count > 0)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotDelete),
						JsonRequestBehavior.AllowGet);
			}

			var result = await DbContext.ScheduleEventMaster
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result != null)
			{
				if (result.ScheduleStatus == ConstValues.ScheduleStatus.已安排)
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotDelete),
							JsonRequestBehavior.AllowGet);
				}

				DbContext.ScheduleEventMaster.Remove(result);
				await DbContext.SaveChangesAsync();

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[Route("DownloadImportTemplate/{conferenceId}")]
		public async Task<ActionResult> DownloadImportTemplate(string conferenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", conferenceId);

			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID == conferenceId);

			if (conferenceMaster.IsInternational)
			{
				return File(Resources.import_scheduleEventEN,
						"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
						$"import_scheduleEventEN.xlsx");
			}
			else
			{
				return File(Resources.import_scheduleEventCN,
						"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
						$"import_scheduleEventCN.xlsx");
			}
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Import/{ConferenceId}")]
		public async Task<JsonResult> Import(ConferenceScheduleEventModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			if (model.ImportFile != null && model.ImportFile.InputStream.Length > 0)
			{
				try
				{
					var result = await this.ImportData(model.ConferenceId, model.ImportFile.InputStream);

					if (!string.IsNullOrEmpty(_importMessage))
					{
						return JsonCamelCase(Utility.CreateFailJsonResult(_importMessage),
								JsonRequestBehavior.AllowGet, true);
					}
					else
					{
						return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessImport),
								JsonRequestBehavior.AllowGet, true);
					}
				}
				catch (Exception)
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgFileError),
							JsonRequestBehavior.AllowGet, true);
				}
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgInvalidFile),
					JsonRequestBehavior.AllowGet, true);
			}
		}

		private async Task<int> ImportData(string conferenceId, Stream stream)
		{
			var conferenceInfo = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID == conferenceId);

			XSSFWorkbook workbook;
			workbook = new XSSFWorkbook(stream);

			ISheet sheet = workbook.GetSheetAt(0);
			int rowIndex = 0;
			int recordCount = 0;

			while (true)
			{
				var tmpMsg = string.Empty;
				try
				{
					rowIndex++;
					IRow row = sheet.GetRow(rowIndex);
					if (row == null)
					{
						break;
					}

					var model = new ConferenceScheduleEventModel()
					{
						ConferenceId = conferenceId
					};
					int columnIndex = 0;

					// 环节名称
					model.EventName = Utility.ReadExcelField(row.GetCell(columnIndex));
					if (string.IsNullOrEmpty(model.EventName))
					{
						continue;
					}
					else if (model.EventName.Length > 100)
					{
						tmpMsg += string.Format(Resources.MsgImportMaxLength, model.EventName, Resources.EventName, 100) + "<br/>";
					}
					model.EventName = model.EventName.Replace(ConstValues.strHtmlEnter, string.Empty).Replace(ConstValues.strHtmlChengeLine, string.Empty);

					// 环节时长
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						double duration;
						if (row.GetCell(columnIndex).CellType == CellType.Numeric)
						{
							if (double.TryParse(row.GetCell(columnIndex)?.NumericCellValue.ToString(), out duration))
							{
								model.Duration = duration;
							}
							else
							{
								tmpMsg += string.Format(Resources.MsgEventDuration, row.GetCell(columnIndex)?.NumericCellValue.ToString()) + "<br/>";
							}
						}
						else
						{
							if (double.TryParse(row.GetCell(columnIndex)?.StringCellValue, out duration))
							{
								model.Duration = duration;
							}
							else
							{
								tmpMsg += string.Format(Resources.MsgEventDuration, row.GetCell(columnIndex)?.StringCellValue) + "<br/>";
							}
						}
					}

					// 专题名称
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.TopicName = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.TopicName.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.EventName, Resources.TopicName, 100) + "<br/>";
						}
						else
						{
							var topicMaster = await DbContext.TopicMaster.AsNoTracking()
									.FirstOrDefaultAsync(x => x.ConferenceId == conferenceId &&
										x.TopicName == model.TopicName);

							if (topicMaster == null)
							{
								tmpMsg += string.Format(Resources.MsgImportNotExist, model.EventName, Resources.TopicName) + "<br/>";
							}
							else
							{
								model.TopicId = topicMaster.ID;
							}
						}

					}

					// 备注
					columnIndex++;
					if (row.GetCell(columnIndex) != null)
					{
						model.Remark = Utility.ReadExcelField(row.GetCell(columnIndex));

						if (model.Remark.Length > 100)
						{
							tmpMsg += string.Format(Resources.MsgImportMaxLength, model.EventName, Resources.Remark, 100) + "<br/>";
						}
					}

					if (!string.IsNullOrEmpty(tmpMsg))
					{
						_importMessage += tmpMsg;
						continue;
					}

					var scheduleEventMaster = new ScheduleEventMaster
					{
						ID = Utility.GetTableId(ConstValues.TableName.ScheduleEventMaster),
						ConferenceId = model.ConferenceId,
						EventName = model.EventName?.Trim(),
						Duration = model.Duration,
						TopicId = model.TopicId,
						Chairman = string.Empty,
						ChairmanMail = string.Empty,
						ScheduleStatus = ConstValues.ScheduleStatus.待安排,
						Status = ConstValues.Status.正常,
						Sort = ConstValues.DefaultSort,
						Remark = model.Remark,
						Creator = LoginUser.UserName,
						CreateIP = LoginUser.IP,
						CreateDate = DateTime.Now
					};
					DbContext.ScheduleEventMaster.Add(scheduleEventMaster);
					await DbContext.SaveChangesAsync();

					recordCount++;
				}
				catch (Exception)
				{
					continue;
				}
			}

			return await Task.FromResult(recordCount);
		}
	}
}